package com.school.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.school.common.PageResult;
import com.school.common.ResultCode;
import com.school.entity.Student;
import com.school.exception.BusinessException;
import com.school.mapper.StudentMapper;
import com.school.service.StudentService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 学生信息服务实现类
 * 
 * @author School Development Team
 * @version 1.0.0
 * @since 2024
 */
@Service
@Transactional(rollbackFor = Exception.class)
public class StudentServiceImpl extends ServiceImpl<StudentMapper, Student> implements StudentService {

    @Override
    public StudentMapper getBaseMapper() {
        return super.getBaseMapper();
    }

    @Override
    public PageResult<Student> getStudentPage(Long current, Long size, Map<String, Object> params) {
        Page<Student> page = new Page<>(current, size);
        IPage<Student> result = baseMapper.selectStudentPage(page, params);
        return PageResult.of(result);
    }

    @Override
    public Student getStudentDetail(String studentId) {
        if (!StringUtils.hasText(studentId)) {
            throw new BusinessException(ResultCode.PARAM_ERROR, "学生ID不能为空");
        }
        Student student = baseMapper.selectStudentDetailById(studentId);
        if (student == null) {
            throw new BusinessException(ResultCode.STUDENT_NOT_FOUND);
        }
        return student;
    }

    @Override
    public boolean addStudent(Student student) {
        // 验证学生信息
        Map<String, String> validationResult = validateStudent(student);
        if (!validationResult.isEmpty()) {
            throw new BusinessException(ResultCode.PARAM_ERROR, 
                String.join(", ", validationResult.values()));
        }

        // 检查学生ID是否已存在
        if (getById(student.getStudentId()) != null) {
            throw new BusinessException(ResultCode.STUDENT_ALREADY_EXISTS);
        }

        // 检查身份证号是否已存在
        if (StringUtils.hasText(student.getIdCard()) && isIdCardExists(student.getIdCard(), null)) {
            throw new BusinessException(ResultCode.STUDENT_ID_CARD_EXISTS);
        }

        // 设置默认状态
        if (!StringUtils.hasText(student.getStatus())) {
            student.setStatus("active");
        }

        return save(student);
    }

    @Override
    public boolean updateStudent(Student student) {
        if (!StringUtils.hasText(student.getStudentId())) {
            throw new BusinessException(ResultCode.PARAM_ERROR, "学生ID不能为空");
        }

        // 检查学生是否存在
        Student existingStudent = getById(student.getStudentId());
        if (existingStudent == null) {
            throw new BusinessException(ResultCode.STUDENT_NOT_FOUND);
        }

        // 验证学生信息
        Map<String, String> validationResult = validateStudent(student);
        if (!validationResult.isEmpty()) {
            throw new BusinessException(ResultCode.PARAM_ERROR, 
                String.join(", ", validationResult.values()));
        }

        // 检查身份证号是否已存在（排除当前学生）
        if (StringUtils.hasText(student.getIdCard()) && 
            isIdCardExists(student.getIdCard(), student.getStudentId())) {
            throw new BusinessException(ResultCode.STUDENT_ID_CARD_EXISTS);
        }

        return updateById(student);
    }

    @Override
    public boolean deleteStudent(String studentId) {
        if (!StringUtils.hasText(studentId)) {
            throw new BusinessException(ResultCode.PARAM_ERROR, "学生ID不能为空");
        }

        Student student = getById(studentId);
        if (student == null) {
            throw new BusinessException(ResultCode.STUDENT_NOT_FOUND);
        }

        // 检查学生状态，只有非活跃状态才能删除
        if ("active".equals(student.getStatus())) {
            throw new BusinessException(ResultCode.OPERATION_NOT_ALLOWED, "活跃状态的学生不能删除");
        }

        return removeById(studentId);
    }

    @Override
    public boolean batchDeleteStudents(List<String> studentIds) {
        if (studentIds == null || studentIds.isEmpty()) {
            throw new BusinessException(ResultCode.PARAM_ERROR, "学生ID列表不能为空");
        }

        // 检查所有学生是否都存在且可删除
        List<Student> students = listByIds(studentIds);
        if (students.size() != studentIds.size()) {
            throw new BusinessException(ResultCode.STUDENT_NOT_FOUND, "部分学生不存在");
        }

        // 检查是否有活跃状态的学生
        List<String> activeStudents = students.stream()
            .filter(s -> "active".equals(s.getStatus()))
            .map(Student::getName)
            .collect(Collectors.toList());
        
        if (!activeStudents.isEmpty()) {
            throw new BusinessException(ResultCode.OPERATION_NOT_ALLOWED, 
                "以下活跃状态的学生不能删除: " + String.join(", ", activeStudents));
        }

        return removeByIds(studentIds);
    }

    @Override
    public List<Student> getStudentsByClassId(String classId) {
        if (!StringUtils.hasText(classId)) {
            return Collections.emptyList();
        }
        return baseMapper.selectStudentsByClassId(classId);
    }

    @Override
    public Student getStudentByIdCard(String idCard) {
        if (!StringUtils.hasText(idCard)) {
            return null;
        }
        return baseMapper.selectStudentByIdCard(idCard);
    }

    @Override
    public boolean isIdCardExists(String idCard, String excludeStudentId) {
        if (!StringUtils.hasText(idCard)) {
            return false;
        }
        
        LambdaQueryWrapper<Student> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Student::getIdCard, idCard);
        if (StringUtils.hasText(excludeStudentId)) {
            wrapper.ne(Student::getStudentId, excludeStudentId);
        }
        
        return count(wrapper) > 0;
    }

    @Override
    public boolean transferClass(String studentId, String newClassId) {
        if (!StringUtils.hasText(studentId) || !StringUtils.hasText(newClassId)) {
            throw new BusinessException(ResultCode.PARAM_ERROR, "学生ID和班级ID不能为空");
        }

        Student student = getById(studentId);
        if (student == null) {
            throw new BusinessException(ResultCode.STUDENT_NOT_FOUND);
        }

        if ("active".equals(student.getStatus())) {
            student.setClassId(newClassId);
            return updateById(student);
        } else {
            throw new BusinessException(ResultCode.STUDENT_STATUS_ERROR, "只有活跃状态的学生才能转班");
        }
    }

    @Override
    public boolean batchTransferClass(List<String> studentIds, String newClassId) {
        if (studentIds == null || studentIds.isEmpty() || !StringUtils.hasText(newClassId)) {
            throw new BusinessException(ResultCode.PARAM_ERROR, "学生ID列表和班级ID不能为空");
        }

        return baseMapper.batchUpdateStudentClass(studentIds, newClassId) > 0;
    }

    @Override
    public boolean updateStudentStatus(String studentId, String status) {
        if (!StringUtils.hasText(studentId) || !StringUtils.hasText(status)) {
            throw new BusinessException(ResultCode.PARAM_ERROR, "学生ID和状态不能为空");
        }

        Student student = getById(studentId);
        if (student == null) {
            throw new BusinessException(ResultCode.STUDENT_NOT_FOUND);
        }

        student.setStatus(status);
        return updateById(student);
    }

    @Override
    public boolean batchUpdateStudentStatus(List<String> studentIds, String status) {
        if (studentIds == null || studentIds.isEmpty() || !StringUtils.hasText(status)) {
            throw new BusinessException(ResultCode.PARAM_ERROR, "学生ID列表和状态不能为空");
        }

        return baseMapper.batchUpdateStudentStatus(studentIds, status) > 0;
    }

    @Override
    public List<Map<String, Object>> getStudentCountByClass() {
        return baseMapper.countStudentsByClass();
    }

    @Override
    public List<Map<String, Object>> getStudentCountByGrade() {
        return baseMapper.countStudentsByGrade();
    }

    @Override
    public List<Map<String, Object>> getStudentCountByStatus() {
        return baseMapper.countStudentsByStatus();
    }

    @Override
    public List<Student> getStudentsByGuardianPhone(String guardianPhone) {
        if (!StringUtils.hasText(guardianPhone)) {
            return Collections.emptyList();
        }
        return baseMapper.selectStudentsByGuardianPhone(guardianPhone);
    }

    @Override
    public List<Student> getGraduatingStudents(Integer graduationYear) {
        if (graduationYear == null) {
            graduationYear = LocalDate.now().getYear();
        }
        return baseMapper.selectGraduatingStudents(graduationYear);
    }

    @Override
    public List<Student> getNewEnrollmentStudents(String startDate, String endDate) {
        return baseMapper.selectNewEnrollmentStudents(startDate, endDate);
    }

    @Override
    public List<Student> getStudentsWithoutClass() {
        return baseMapper.selectStudentsWithoutClass();
    }

    @Override
    public List<Student> getStudentsByAgeRange(Integer minAge, Integer maxAge) {
        return baseMapper.selectStudentsByAgeRange(minAge, maxAge);
    }

    @Override
    public Long getTotalStudentCount() {
        return baseMapper.countTotalStudents();
    }

    @Override
    public Long getActiveStudentCount() {
        return baseMapper.countActiveStudents();
    }

    @Override
    public List<Student> searchStudents(String keyword) {
        if (!StringUtils.hasText(keyword)) {
            return Collections.emptyList();
        }
        return baseMapper.searchStudents(keyword);
    }

    @Override
    public Map<String, Object> importStudents(List<Student> students) {
        Map<String, Object> result = new HashMap<>();
        int successCount = 0;
        int failCount = 0;
        List<String> errorMessages = new ArrayList<>();

        for (Student student : students) {
            try {
                // 生成学生ID（如果没有）
                if (!StringUtils.hasText(student.getStudentId())) {
                    String classId = student.getClassId();
                    Integer enrollmentYear = student.getEnrollmentDate() != null ? 
                        student.getEnrollmentDate().getYear() : LocalDate.now().getYear();
                    student.setStudentId(generateStudentId(classId, enrollmentYear));
                }

                addStudent(student);
                successCount++;
            } catch (Exception e) {
                failCount++;
                errorMessages.add(String.format("学生 %s 导入失败: %s", 
                    student.getName(), e.getMessage()));
            }
        }

        result.put("total", students.size());
        result.put("success", successCount);
        result.put("fail", failCount);
        result.put("errors", errorMessages);

        return result;
    }

    @Override
    public List<Student> exportStudents(Map<String, Object> params) {
        LambdaQueryWrapper<Student> wrapper = new LambdaQueryWrapper<>();
        
        // 根据参数构建查询条件
        if (params.containsKey("classId")) {
            wrapper.eq(Student::getClassId, params.get("classId"));
        }
        if (params.containsKey("status")) {
            wrapper.eq(Student::getStatus, params.get("status"));
        }
        if (params.containsKey("gradeLevel")) {
            // 这里需要关联班级表查询，暂时简化处理
        }
        
        return list(wrapper);
    }

    @Override
    public String generateStudentId(String classId, Integer enrollmentYear) {
        // 生成规则：年份(4位) + 班级ID(2位) + 序号(3位)
        // 例如：2024010001
        
        if (enrollmentYear == null) {
            enrollmentYear = LocalDate.now().getYear();
        }
        
        String prefix = enrollmentYear.toString();
        if (StringUtils.hasText(classId) && classId.length() >= 2) {
            prefix += classId.substring(classId.length() - 2);
        } else {
            prefix += "00";
        }
        
        // 查询当前最大序号
        LambdaQueryWrapper<Student> wrapper = new LambdaQueryWrapper<>();
        wrapper.likeRight(Student::getStudentId, prefix)
               .orderByDesc(Student::getStudentId)
               .last("LIMIT 1");
        
        Student lastStudent = getOne(wrapper);
        int nextSeq = 1;
        
        if (lastStudent != null && lastStudent.getStudentId().length() >= 10) {
            String seqStr = lastStudent.getStudentId().substring(6);
            try {
                nextSeq = Integer.parseInt(seqStr) + 1;
            } catch (NumberFormatException e) {
                nextSeq = 1;
            }
        }
        
        return prefix + String.format("%04d", nextSeq);
    }

    @Override
    public Map<String, String> validateStudent(Student student) {
        Map<String, String> errors = new HashMap<>();
        
        if (!StringUtils.hasText(student.getName())) {
            errors.put("name", "姓名不能为空");
        }
        
        if (!StringUtils.hasText(student.getGender()) || 
            (!"M".equals(student.getGender()) && !"F".equals(student.getGender()))) {
            errors.put("gender", "性别必须是M或F");
        }
        
        if (StringUtils.hasText(student.getIdCard())) {
            if (!student.getIdCard().matches("^[1-9]\\d{5}(18|19|20)\\d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)\\d{3}[0-9Xx]$")) {
                errors.put("idCard", "身份证号格式不正确");
            }
        }
        
        if (StringUtils.hasText(student.getPhone())) {
            if (!student.getPhone().matches("^1[3-9]\\d{9}$")) {
                errors.put("phone", "手机号格式不正确");
            }
        }
        
        if (StringUtils.hasText(student.getGuardianPhone())) {
            if (!student.getGuardianPhone().matches("^1[3-9]\\d{9}$")) {
                errors.put("guardianPhone", "监护人手机号格式不正确");
            }
        }
        
        return errors;
    }
}